#ifndef _ICELL_H
#define _ICELL_H

#include "point.h"

#include <iostream>
#include <vector>

// =============================================================================
//  Déclaration de la classe virtuelle i-cellule : VirtualICell
// =============================================================================

class VirtualICell
{
	public:
		virtual ~VirtualICell() {}
		
		virtual int GetDim() const = 0;
		virtual const std::vector<VirtualICell*>* GetBorderCells() = 0;
		virtual void Display() = 0;
};


// =============================================================================
//  Déclaration de la classe i-cellule : ICell
//  Hérite de VirtualICell.
// =============================================================================

static int nbCellCreate = 0;
static int nbCellDelete = 0;

template<int t_iDimCell, int t_iDimPoint, typename t_Type>
class ICell : public VirtualICell
{
	public:
		ICell();
		ICell(std::vector<VirtualICell*> p_picBorderCells) : m_picBorderCells(p_picBorderCells) {}
		~ICell();
		
		int GetDim() const { return t_iDimCell; }
		const std::vector<VirtualICell*>* GetBorderCells() { return &m_picBorderCells; }
		void Display();

	private:
		std::vector<VirtualICell*> m_picBorderCells;
};



// =============================================================================
//  Spécialisation de i-cellule pour les cellules de dimmension 0.
//  Hérite de VirtualICell.
// =============================================================================

template<int t_iDimPoint, typename t_Type>
class ICell<0, t_iDimPoint, t_Type> : public VirtualICell
{
	public:
		ICell() : m_pPoint(*(new Point<t_iDimPoint, t_Type>())) {}
		ICell(Point<t_iDimPoint, t_Type>& p_pPoint) : m_pPoint(p_pPoint) {}
		~ICell() { delete &m_pPoint; std::cout << "Destructeur de 0-Cell" << std::endl; }
		
		int GetDim() const { return 0; }
		const std::vector<VirtualICell* >* GetBorderCells() { return NULL; }
		const Point<t_iDimPoint, t_Type>& GetPoint() const { return m_pPoint; }
		void Display();
		
	private:
		Point<t_iDimPoint, t_Type>& m_pPoint;
};

// =============================================================================
//  Implémentation des fonctions membres.
// =============================================================================

template<int t_iDimCell, int t_iDimPoint, typename t_Type>
ICell<t_iDimCell, t_iDimPoint, t_Type>::ICell()
{
	for(int i = 0; i < 2 * t_iDimCell; i++)
		m_picBorderCells.push_back(new ICell<t_iDimCell - 1, t_iDimPoint, t_Type>());
}

// -----------------------------------------------------------------------------
template<int t_iDimCell, int t_iDimPoint, typename t_Type>
ICell<t_iDimCell, t_iDimPoint, t_Type>::~ICell()
{
	for (int i = 0; i < m_picBorderCells.size(); i++)
		m_picBorderCells.pop_back();
	
	std::cout << "Destructeur de ICell" << std::endl;
	/*delete m_picBorderCells[i];
	m_picBorderCells.erase(m_picBorderCells.begin(), m_picBorderCells.end());*/
}

// -----------------------------------------------------------------------------
template<int t_iDimCell, int t_iDimPoint, typename t_Type>
void ICell<t_iDimCell, t_iDimPoint, t_Type>::Display()
{
	std::cout << "Dimension " << t_iDimCell << std::endl;
	for (int i = 0; i < m_picBorderCells.size(); i++)
		m_picBorderCells[i]->Display();
}


// =============================================================================
//  Implémentation des fonctions membres.
//  Spécifique à la dimension 0.
// =============================================================================

template<int t_iDimPoint, typename t_Type>
void ICell<0, t_iDimPoint, t_Type>::Display()
{
	std::cout << "Dimension 0" << std::endl;
	for (int i = 0; i < t_iDimPoint; i++)
		std::cout << "point " << i << " : " << m_pPoint.GetCoordonate(i) << std::endl;
}

#endif // _ICELL_H
